<?php

namespace app\data\service;

use think\admin\Exception;
use think\admin\Service;
use think\db\exception\DbException;
use think\facade\Cache;
use think\facade\Log;

/**
 * 用户数据管理服务
 * Class UserAdminService
 * @package app\data\service
 */
class UserAdminService extends Service
{
    const API_TYPE_WAP = 'wap';
    const API_TYPE_WEB = 'web';
    const API_TYPE_WXAPP = 'wxapp';
    const API_TYPE_WECHAT = 'wechat';
    const API_TYPE_IOSAPP = 'iosapp';
    const API_TYPE_ANDROID = 'android';

    const TYPES = [
        // 接口支付配置（不需要的直接注释）
        self::API_TYPE_WAP     => [
            'name' => '手机浏览器',
            'auth' => 'phone',
        ],
        self::API_TYPE_WEB     => [
            'name' => '电脑浏览器',
            'auth' => 'phone',
        ],
        self::API_TYPE_WXAPP   => [
            'name' => '微信小程序',
            'auth' => 'openid1',
        ],
        self::API_TYPE_WECHAT  => [
            'name' => '微信服务号',
            'auth' => 'openid2',
        ],
        self::API_TYPE_IOSAPP  => [
            'name' => '苹果APP应用',
            'auth' => 'phone',
        ],
        self::API_TYPE_ANDROID => [
            'name' => '安卓APP应用',
            'auth' => 'phone',
        ],
    ];

    /**
     * 格式化user字段
     * @param $user
     * @return mixed
     */
    public function formatUserField($user, $more = true)
    {
        unset(
            $user['deleted'],
        );

        if (empty($user['id'])) {
            return [];
        }

        if (empty($user['headimg'])) {
            $user['headimg'] = 'https://car-review666.oss-cn-shenzhen.aliyuncs.com/default-image/ee7fd7a6445d1c3c373b1c53ea0442c.jpg';
        }

        if (empty($user['nickname'])) {
            $user['nickname'] = '真惠审' . (($user['id'] ?? 0) + 1000);
        }

        return $user;
    }

    /**
     * 更新用户用户参数
     * @param array $map 查询条件
     * @param array $data 更新数据
     * @param string $type 接口类型
     * @param boolean $force 强刷令牌
     * @return array
     * @throws Exception
     * @throws DbException
     */
    public function set(array $map, array $data, string $type, bool $force = false): array
    {
        if (!empty($data['id'])) {
            $uuid = $data['id'];
        } else {
            $uuid = $this->app->db->name('DataUser')->where($map)->where(['deleted' => 0])->value('id');
        }
        if (!$uuid) {
            $data['invite_code'] = $this->inviteCode();
            $uuid = $this->app->db->name('DataUser')->strict(false)->insertGetId($data);

            $couponIds = $this->app->db->name('car_coupons')->where('type', 'new')->where('status', 1)->select()->toArray();
            foreach ($couponIds as $coupon) {
                try {
                    CouponService::instance()->gotCoupon($coupon['id'], $uuid);
                } catch (\Exception $exception) {
                    Log::error($exception->getMessage());
                }
            }
        }
        unset($data['id'], $data['deleted'], $data['create_at'], $data['verify']);
        if (!empty($data)) {
            $map = ['id' => $uuid, 'deleted' => 0];
            $data['last_login_at'] = date('Y-m-d H:i:s', time());
            $this->app->db->name('DataUser')->strict(false)->where($map)->update($data);
        }

        $cacheKey = config('cacheKey.uid2user') . $uuid;
        Cache::delete($cacheKey);

        if ($force) {
            UserTokenService::instance()->token(intval($uuid), $type);
        }
        return $this->get($uuid, $type);
    }

    /**
     * 获取用户数据
     * @param integer $uuid 用户UID
     * @param ?string $type 接口类型
     * @return array
     * @throws DbException
     * @throws Exception
     */
    public function get($uuid, ?string $type = null, bool $formatUser = true): array
    {
        $cacheKey = config('cacheKey.uid2user') . $uuid;
        $user = Cache::get($cacheKey);
        if (!$user) {
            $user = $this->app->db->name('DataUser')->where(['id' => $uuid, 'deleted' => 0])->findOrEmpty();

            if (empty($user)) return [];
            Cache::set($cacheKey, $user);

            if (is_null($type)) {
                $type = self::API_TYPE_ANDROID;
            }
            [$state, $info, $data] = UserTokenService::instance()->token($uuid, $type);
            if (empty($state) || empty($data)) throw new Exception($info);
            $user['token'] = ['token' => $data['token'], 'expire' => $data['time']];
        }

        if ($formatUser) {
            $user = $this->formatUserField($user);
        }

        return $user;
    }

    /**
     * 获取父级用户名称
     * @param int $uuid
     * @return array|string
     */
    public function getPidName($uuid)
    {
        $cacheKey = config('cacheKey.uid2user') . $uuid;
        $user = Cache::get($cacheKey);
        if (!$user) {
            $user = $this->app->db->name('DataUser')->where(['id' => $uuid, 'deleted' => 0])->findOrEmpty();
            if (empty($user)) return '';
            Cache::set($cacheKey, $user);
        }

        if (empty($user['nickname'])) {
            $user['nickname'] = '用户' . ($user['id'] ?? 0);
        }

        return $user['nickname'] ?? '';
    }

    /**
     * 获取用户查询条件
     * @param string $field 认证字段
     * @param string $openid 用户OPENID值
     * @param string $unionid 用户UNIONID值
     * @return array
     */
    public function getUserUniMap(string $field, string $openid, string $unionid = ''): array
    {
        if (!empty($unionid)) {
            [$map1, $map2] = [[['unionid', '=', $unionid]], [[$field, '=', $openid]]];
            if ($uuid = $this->app->db->name('DataUser')->whereOr([$map1, $map2])->value('id')) {
                return ['id' => $uuid];
            }
        }
        return [$field => $openid];
    }

    /**
     * 列表绑定用户数据
     * @param array $list 原数据列表
     * @param string $keys 用户UID字段
     * @param string $bind 绑定字段名称
     * @param string $cols 返回用户字段
     * @return array
     */
    public function buildByUid(array &$list, string $keys = 'uuid', string $bind = 'user', string $cols = '*'): array
    {
        if (count($list) < 1) return $list;
        $uids = array_unique(array_column($list, $keys));
        $users = $this->app->db->name('DataUser')->whereIn('id', $uids)->column($cols, 'id');
        foreach ($list as &$vo) $vo[$bind] = $users[$vo[$keys]] ?? [];
        return $list;
    }

    /**
     * 用户是否绑定银行卡
     * @param $userId
     * @return int
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function isBindBankByUserId($userId): int
    {
        $isBind = $this->app->db->name('DataUserBank')->where('uuid', $userId)->where('deleted', 0)->where('status', 1)->find();
        return $isBind ? 1 : 0;
    }

    /**
     * 用户是否服务商
     * @param $user
     * @return int
     */
    public function isServiceProvider($user): int
    {
        if ($user['service_provider_status'] === 1) {
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * 获取随机邀请码
     * @return false|string
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function inviteCode()
    {
        $randStr = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890');
        $rand = substr($randStr,0,6);
        if ($this->app->db->name('DataUser')->where('invite_code', $rand)->find()) {
            $this->inviteCode();
        }

        return $rand;
    }
}